<template>
  <div class="common-map">
    <div id="map-container"
      class="map-container"></div>
  </div>
</template>

<script>
  import * as echarts from 'echarts';
  const wellknown = require('wellknown');
  import Draw from '@/utils/map/leafletDraw.js';
  import { getMaxMinLngLat } from '@/utils/map/mapTool.js';
  const HeatmapOverlay = require('leaflet-heatmap');
  const eleResizeDetector = require('element-resize-detector');

  const mapConfig = {
    // 基础底图
    baseLayerUrl: 'http://t{s}.tianditu.gov.cn/DataServer?T=img_c&X={x}&Y={y}&L={z}&tk=ffa5ef8e4ea43caf693fa0097f8258a6',
    // 基础底图注记
    baseLabelLayer: 'http://t{s}.tianditu.gov.cn/DataServer?T=cia_c&X={x}&Y={y}&L={z}&tk=ffa5ef8e4ea43caf693fa0097f8258a6'
    // // 国界
    // nationalBoundaries: 'http://49.4.8.203:8091/mapserver/vmap/WMTS/1.0/xzqh_gj/xzqh_gj/getTile/{z}/{y}/{x}',
    // // 市县区划
    // shengshixianBoundaries: 'http://49.4.8.203:8091/mapserver/vmap/WMTS/1.0/xzqh/xzqh/getTile/{z}/{y}/{x}',
    // // 注记
    // baseLabelZJLayer: 'http://49.4.8.203:8091/mapserver/label/WMTS/1.0/xzqh_zj/xzqh_zj/getTile/{z}/{y}/{x}'
  };

  export default {
    name: 'theMap',
    components: {},
    mixins: [Draw],
    data() {
      return {
        map: null,
        shapeGroup: null,
        curLayer: null,
        markersGroup: null,
        anchorPointGroup: null,
        geojsonGroup: null,
        heatmapLayer: null
      };
    },
    mounted() {
      this.init();
    },
    methods: {
      init() {
        //初始化
        this.map = L.map('map-container', {
          crs: L.CRS.EPSG4326, //坐标系
          center: [35.639, 105.55],
          zoom: 4,
          // 隐藏右下角官方图标
          attributionControl: false,
          // 隐藏左上角zoom控制图标(+ - 按钮)
          zoomControl: false,
          // 地图自适应大小
          invalidateSize: true
          // doubleClickZoom: false
        });

        // 屏幕调整地图重新渲染
        const erd = eleResizeDetector();
        erd.listenTo(this.$el, () => {
          this.map.invalidateSize();
        });

        //引入图层
        L.tileLayer(mapConfig.baseLayerUrl, {
          subdomains: ['0', '1', '2', '3', '4'],
          zoomOffset: 1,
          // 超过17级进行放大，保证不会出现未找到服务的提示
          maxNativeZoom: 17,
          maxZoom: 20
        }).addTo(this.map);

        //引入注记
        L.tileLayer(mapConfig.baseLabelLayer, {
          subdomains: ['0', '1', '2', '3', '4'],
          zoomOffset: 1
        }).addTo(this.map);

        // 边界的geojson集合
        this.borderGroup = new L.LayerGroup();
        // 分层设色的geojson集合
        this.geojsonGroup = new L.LayerGroup();
        // 绘制形状的集合
        this.shapeGroup = new L.FeatureGroup();
        // marker集合
        this.markersGroup = new L.FeatureGroup();
        // 可编辑图形上的锚点
        this.anchorPointGroup = new L.FeatureGroup();

        this.borderGroup.addTo(this.map);
        this.geojsonGroup.addTo(this.map);
        this.shapeGroup.addTo(this.map);
        this.markersGroup.addTo(this.map);
        this.anchorPointGroup.addTo(this.map);
        // 可拖动的
        this.editableRect = new L.FeatureGroup();
        this.editableRect.addTo(this.map);
      },
      /**
       * 画图部分
       */
      offsetPoint(rectPoint, meter) {
        let edg = (meter / (2 * Math.PI * 6371004)) * 360;
        let arr = [[], []];
        arr[0][0] = Number(rectPoint[0][0]) - edg;
        arr[0][1] = Number(rectPoint[0][1]) - edg;
        arr[1][0] = Number(rectPoint[1][0]) + edg;
        arr[1][1] = Number(rectPoint[1][1]) + edg;
        return arr;
      },
      latlngToRect(latlngs) {
        let lats = [];
        let lngs = [];
        latlngs.forEach((latlng) => {
          let { lat, lng } = latlng;
          lats.push(lat);
          lngs.push(lng);
        });
        lats.sort((a, b) => a - b);
        lngs.sort((a, b) => a - b);
        let len1 = lats.length - 1;
        let len2 = lngs.length - 1;
        return [
          [lats[0], lngs[0]],
          [lats[len1], lngs[len2]]
        ];
      },
      // 画可方形
      addRect(list, r = 1000) {
        //会清除图层组里面所有的图层
        this.shapeGroup.clearLayers();
        let newRectPoint = this.offsetPoint(list, r);

        let rectL = L.rectangle(list, { color: '#fff', fillOpacity: 0 });
        let rectL2 = L.rectangle(newRectPoint);
        this.shapeGroup.addLayer(rectL);
        this.shapeGroup.addLayer(rectL2);

        let geoJSON = rectL2.toGeoJSON();
        let wkt = wellknown.stringify(geoJSON);
        this.$emit('getAnalysisResult', { wkt, latlngs: list, radius: r });
      },
      // 添加点再请求数据
      addMaker(latlng, bool, radius) {
        let marker = L.marker(latlng);
        this.markersGroup.addLayer(marker);
        // 画可编辑的圆
        this.addEditableCircle(latlng, radius, (info) => {
          let { radius, wkt } = info;
          this.$emit('getAnalysisResult', { wkt, radius });
        });
      },
      // 地图上绘点
      drawMaker(radius = 1000) {
        this.MapFunc.addCursorStyle(this.map, 'crosshare-cursor');
        let that = this;
        this.map.on('click', function (e) {
          that.markersGroup.clearLayers();
          let lat = e.latlng.lat; //纬度
          let lng = e.latlng.lng; //经度
          that.map.setView([lat, lng], 14);
          let marker = L.marker([lat, lng]);
          that.markersGroup.addLayer(marker);
          that.markersGroup.addTo(that.map);
          // 画可编辑的圆
          that.addEditableCircle([lat, lng], radius, (info) => {
            let { latlng, radius, wkt } = info;
            that.$emit('getLatlng', { latlngs: [latlng], radius, wkt });
          });
          setTimeout(() => {
            that.drawOff();
          }, 200);
        });
      },
      cancelAddMaker() {
        this.MapFunc.removerCoursorStyle(this.map);
        // 移除监听地图点击事件
        this.map.off('click');
      },
      formatLatlng(ele) {
        let { lat, lng } = ele._latlng;
        return [[lat, lng]];
      },
      /**
       * latlng 经纬度 [纬度, 经度]
       * bool 是否请求数据 boolean
       */
      addCircle(latlng, bool) {
        this.shapeGroup.clearLayers();
        let minmaxlatlng = getMaxMinLngLat(latlng[0], latlng[1], 1000);
        let rectPoint = [
          [minmaxlatlng[2], minmaxlatlng[0]],
          [minmaxlatlng[3], minmaxlatlng[1]]
        ];
        let rectL = L.rectangle(rectPoint);
        this.shapeGroup.addLayer(rectL);

        let geojson = rectL.toGeoJSON();
        let wkt = wellknown.stringify(geojson);

        if (bool) {
          this.$emit('getAnalysisResult', { wkt, radius: 1000 });
        } else {
          this.$emit('getLatlng', { latlngs: [latlng], wkt, radius: 1000 });
        }
      },
      toDrawPolygon(type, radius = 1000) {
        this.clearDrawEditable();
        this.drawPolygon(type, (layer) => {
          // 添加长方形
          let latlngs = layer.getLatLngs();
          let rectPoint = this.latlngToRect(latlngs[0]);
          let rectL = L.rectangle(rectPoint, { color: '#fff', fillOpacity: 0 });
          let newRectPoint = this.offsetPoint(rectPoint, radius);

          this.shapeGroup.addLayer(rectL);
          // 可编辑长方形，暂时注释
          // let rectL2 = this.addEditableRect(newRectPoint);
          let rectL2 = L.rectangle(newRectPoint);
          this.shapeGroup.addLayer(rectL2);

          let geoJSON = rectL2.toGeoJSON();
          let wkt = wellknown.stringify(geoJSON);
          this.$emit('getLatlng', { latlngs: newRectPoint, wkt, radius });
        });
      },
      toDrawLine() {
        this.drawPolyline();
      },
      /**
       * geojson部分
       */
      addJsonpr(jsonpr, style) {
        let stylex = style || {
          weight: 5,
          color: 'yellow',
          fill: false
        };
        if (jsonpr) {
          this.borderGroup.clearLayers();
          let borderLayer = L.geoJSON(jsonpr, {
            style: function () {
              return stylex;
            }
          });
          this.borderGroup.addLayer(borderLayer);
          this.map.fitBounds(borderLayer.getBounds());
        }
      },
      toBounds(bounds) {
        if (bounds) {
          this.map.fitBounds(bounds);
        } else {
          this.map.flyTo([35.639, 105.55], 4);
        }
      },
      addColorLayer(obj, colors, type) {
        let { json, list, jsonpr } = obj;
        if (json && list.length) {
          // 添加geojson做分级设色
          this.addJson(json, list, colors);
          // 再加边框
          this.addJsonpr(jsonpr, {
            weight: 5,
            color: 'yellow',
            fill: false
          });
          this.toBounds(jsonpr);
          // 在地图上加多个echarts
          if (type === 'showChart') {
            this.addMulitPieChart(list);
          }
        }
      },
      addJson(json, list, colors) {
        this.geojsonGroup.clearLayers();
        let geojsonLayer = L.geoJSON(json, {
          style: function (feature) {
            let ele = list.find((item) => item.code == feature.properties.adcode);
            let value = ele ? ele.value : '';

            if (value) {
              for (let item of colors) {
                let { min, max, color } = item;
                if (max) {
                  if (value > min && value <= max) {
                    return { color: color, fillOpacity: 0.7 };
                  }
                } else {
                  if (value > min) {
                    return { color: color, fillOpacity: 0.7 };
                  }
                }
              }
            } else {
              return { color: null, fillOpacity: 0 };
            }
          }
        });
        this.geojsonGroup.addLayer(geojsonLayer);
      },
      addMulitPieChart(list) {
        this.markersGroup.clearLayers();
        list.forEach((li) => {
          if (li.counts.length) {
            this.addPieChart({
              name: li.name,
              center: li.center,
              id: li.id,
              data: li.counts
            });
          }
        });
      },
      addPieChart(val) {
        let marker = L.marker(val.center, {
          icon: L.divIcon({
            className: 'leaflet-echart-icon',
            iconSize: [80, 80],
            html:
              '<div id="marker' + val.id + '" style="width: 80px; height: 80px; position: relative; background-color: transparent;"></div>'
          })
        });
        this.markersGroup.addLayer(marker);
        // 基于准备好的dom，初始化echarts实例
        let myChart = echarts.init(document.getElementById('marker' + val.id));
        // 指定图表的配置项和数据
        let option = {
          tooltip: {
            trigger: 'item',
            formatter: () => {
              let arr = [];
              val.data.forEach((ite, i) => {
                arr.push(
                  `<div><div style="width: 10px;height:10px;display:inline-block;border-radius:50%;background-color:${ite.itemStyle.color};"></div><div style="width: 60px;display:inline-block">${ite.name}</div><div style="width: 90px;display:inline-block">${ite.value} 万亩</div><div style="width: 50px;display:inline-block">${ite.percent}</div><div>`
                );
              });
              return `${val.name}<br/>` + arr.join('');
            }
          },
          series: [
            {
              name: '按烟田分组',
              type: 'pie',
              avoidLabelOverlap: false,
              radius: ['50%', '90%'],
              label: {
                show: false
              },
              labelLine: {
                show: false
              },
              data: val.data
            }
          ]
        };
        // 使用刚指定的配置项和数据显示图表。
        myChart.setOption(option);
      },
      addHeatMap(data) {
        const cfg = {
          radius: 8,
          maxOpacity: 0.8,
          scaleRadius: true,
          useLocalExtrema: true,
          latField: 'lat',
          lngField: 'lng',
          valueField: 'count'
        };
        this.heatmapLayer = new HeatmapOverlay(cfg);
        this.heatmapLayer.addTo(this.map);
        this.heatmapLayer.setData(data);
      },
      /**
       * 清除部分
       */
      // 清除绘制的与可编辑的
      clearDrawEditable() {
        this.markersGroup.clearLayers();
        this.shapeGroup.clearLayers();
        this.editableRect.clearLayers();
        this.anchorPointGroup.clearLayers();
        // 清除画线画面
        this.clearTemps();
        this.MapFunc.clearDrawnPolyGon();
        this.drawOff();
      },
      // 清除所有
      clearAll() {
        this.borderGroup.clearLayers();
        this.geojsonGroup.clearLayers();
        if (this.heatmapLayer) {
          this.map.removeLayer(this.heatmapLayer);
        }
        this.clearDrawEditable();
      }
    }
  };
</script>

<style lang="scss" scoped>
  .common-map {
    width: 100%;
    height: 100%;
    .map-container {
      width: 100%;
      height: 100%;
    }
  }
</style>
